﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Web.Security;
using Sharp.Infrastructure;
using Sharp.Platform.Owin;

namespace Sharp.Platform.Configuration
{
    /// <summary>
    /// 用户级配置管理
    /// </summary>
    public class UserConfigManage
    {
        /// <summary>
        /// 缓存
        /// </summary>
        private static readonly Dictionary<Guid, Dictionary<Type, IUserConfig>> Table;
        static UserConfigManage()
        {
            Table = new Dictionary<Guid, Dictionary<Type, IUserConfig>>();
        }
        /// <summary>
        /// 读取用户级配置
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T Read<T>() where T : class,IUserConfig, new()
        {
            string userId = System.Web.HttpContext.Current.Request["UserID"];
            if (userId != null)
            {
                if (userId.Length == 0)
                {
                    return Read<T>(Guid.Empty);
                }
                else
                {
                    return Read<T>(Guid.Parse(userId));
                }
            }

            return Read<T>((Guid)Membership.GetUser().ProviderUserKey);
        }

        /// <summary>
        /// 读取用户级配置
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T Read<T>(Guid userId) where T : class, IUserConfig, new()
        {
            IUserConfig cachedconfig = GetCache(userId, typeof(T));
            if (cachedconfig != null)
            {
                return cachedconfig as T;
            }
            T config = new T();
            string filepath =
                WebServer.MapPath("~/App_Data/User/{0}/{1}"
                    , userId
                    , config.ConfigFileName);
            FileInfo fi = new FileInfo(filepath);

            if (fi.Exists)
            {
                config = SerializableHelper.DeSerialize<T>(fi);
            }
            if (config == null)
            {
                config = new T();
            }

            if (config != null)
            {
                InsertCache(userId, config);
            }

            return config;
        }


        /// <summary>
        /// 读取用户级配置
        /// </summary>
        /// <param name="configType"></param>
        /// <returns></returns>
        public static IUserConfig Read(Type configType)
        {
            IUserConfig configInstance = configType.Assembly.CreateInstance(configType.FullName) as IUserConfig;

            FileInfo fi = new FileInfo(WebServer.MapPath(string.Format("~/App_Data/User/{0}/{1}", SharpUserManager.Current.Id, configInstance.ConfigFileName)));

            var userconfig = SerializableHelper.DeSerialize(fi, configType) as IUserConfig;
            //如果没有配置那么就用默认值
            if (userconfig == null)
            {
                userconfig = configInstance;
            }
            return userconfig;
        }
        /// <summary>
        /// 保存配置
        /// </summary>
        /// <param name="config"></param>
        public static void Save(IUserConfig config)
        {
            string dirpath = WebServer.MapPath(string.Format("~/App_Data/User/{0}/", SharpUserManager.Current.Id));
            DirectoryInfo di = new DirectoryInfo(dirpath);
            if (!di.Exists)
            {
                di.Create();
            }
            SerializableHelper.Serialize(config, dirpath + config.ConfigFileName);

            RemoveCache(SharpUserManager.Current.Id, config.GetType());
        }

        /// <summary>
        /// 设置值
        /// </summary>
        /// <param name="typeFullName"></param>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        /// <remarks>顺便保存了配置文件</remarks>
        public static void SetValue(string typeFullName, string propertyName, string value)
        {
            Type cfg = ConfigManage.UserConfigs(typeFullName);
            var config = Read(cfg);
            PropertyInfo pi = config.GetType().GetProperty(propertyName);
            if (pi != null)
            {
                pi.SetValue(config, Convert.ChangeType(value, pi.PropertyType), null);
                Save(config);
            }
        }
        /// <summary>
        /// 获取属性
        /// </summary>
        /// <param name="configType"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static PropertyInfo GetProperty(Type configType, string propertyName)
        {
            var userconfig = Read(configType);
            var property = userconfig.GetType().GetProperty(propertyName);

            return property;
        }
        private static object InsertLock = new object();

        /// <summary>
        /// 添加缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="userid"></param>
        /// <param name="config"></param>
        private static void InsertCache<T>(Guid userid, T config) where T : class, IUserConfig, new()
        {
            lock (InsertLock)
            {
                Dictionary<Type, IUserConfig> configDic;
                if (Table.TryGetValue(userid, out configDic))
                {
                    if (!configDic.ContainsKey(config.GetType()))
                        configDic.Add(config.GetType(), config);
                }
                else
                {
                    configDic = new Dictionary<Type, IUserConfig>
                    {
                        {config.GetType(), config}
                    };
                    Table.Add(userid, configDic);
                }
            }
        }

        /// <summary>
        /// 获取缓存
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private static IUserConfig GetCache(Guid userid, Type type)
        {
            Dictionary<Type, IUserConfig> userconfigs = new Dictionary<Type, IUserConfig>();
            if (!Table.TryGetValue(userid, out userconfigs))
            {
                return null;
            }
            IUserConfig config;
            if (!userconfigs.TryGetValue(type, out config))
            {
                return null;
            }
            return config;
        }
        /// <summary>
        /// 清楚缓存
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="type"></param>
        private static void RemoveCache(Guid userid, Type type)
        {
            Dictionary<Type, IUserConfig> configDic;
            if (Table.TryGetValue(userid, out configDic))
            {
                configDic.Remove(type);
            }
        }
    }
}